package com.ruicar.afs.cloud.basic.proceeds.debit.controller;

import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruicar.afs.cloud.basic.common.entity.BasicMainInfo;
import com.ruicar.afs.cloud.basic.common.service.BasicMainInfoService;
import com.ruicar.afs.cloud.basic.proceeds.debit.condition.DebitBatchCondition;
import com.ruicar.afs.cloud.basic.proceeds.debit.entity.BasicDebitBatch;
import com.ruicar.afs.cloud.basic.proceeds.debit.entity.BasicDebitBatchDetails;
import com.ruicar.afs.cloud.basic.proceeds.debit.entity.BasicDebitHistory;
import com.ruicar.afs.cloud.basic.proceeds.debit.entity.BasicDebitRecord;
import com.ruicar.afs.cloud.basic.proceeds.debit.service.BasicDebitBatchDetailsService;
import com.ruicar.afs.cloud.basic.proceeds.debit.service.BasicDebitBatchService;
import com.ruicar.afs.cloud.basic.proceeds.debit.service.BasicDebitHistoryService;
import com.ruicar.afs.cloud.basic.proceeds.debit.service.BasicDebitRecordService;
import com.ruicar.afs.cloud.basic.proceeds.debit.vo.DebitBatchDetailVo;
import com.ruicar.afs.cloud.basic.proceeds.debit.vo.DebitDetailRecordVo;
import com.ruicar.afs.cloud.batch.service.AfsBatchInfoService;
import com.ruicar.afs.cloud.common.core.exception.AfsBaseException;
import com.ruicar.afs.cloud.common.core.util.IResponse;
import com.ruicar.afs.cloud.common.modules.contract.enums.*;
import com.ruicar.afs.cloud.common.util.EmptyUtils;
import com.ruicar.afs.cloud.manage.api.dto.PrepaymentDebitDealStatusDto;
import com.ruicar.afs.cloud.manage.api.dto.PrepaymentInfoDto;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.propertyeditors.CustomDateEditor;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.*;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.function.Function;

/**
 * <p>Description: </p>
 *
 * @author ZC.GUO
 * @version 1.0
 * @date create on 2020-06-13 15:09
 */
@Slf4j
@RestController
@Api("扣款管理")
@RequestMapping("/debit")
public class DebitManagementController {
    @Autowired
    private BasicDebitBatchService basicDebitBatchService;
    @Autowired
    private BasicDebitBatchDetailsService basicDebitBatchDetailsService;
    @Autowired
    private BasicDebitRecordService basicDebitRecordService;
    @Autowired
    private BasicDebitHistoryService basicDebitHistoryService;
    @Autowired
    private BasicMainInfoService basicMainInfoService;
    @Autowired
    private AfsBatchInfoService afsBatchInfoService;

    public Date getBatchDate(){
        return DateUtil.parse(afsBatchInfoService.getSystemBatchInfo("icos").getBatchDate(), DatePattern.PURE_DATE_PATTERN);
    }



    @PostMapping(value = "/debitForPrepaymentImmediately")
    @ApiOperation(value = "处理立即进行扣款的提前还款扣款指令")
    public IResponse<PrepaymentDebitDealStatusDto> debitForPrepaymentImmediately(@RequestBody PrepaymentInfoDto prepaymentInfoDto) {
        /**  合同号校验 by ZC.GUO  **/
        BasicMainInfo mainInfo = basicMainInfoService.getOne(Wrappers.<BasicMainInfo>query().lambda()
                .eq(BasicMainInfo::getContractNo,prepaymentInfoDto.getContractNo())
        );
        if (EmptyUtils.isEmpty(mainInfo)){
            return IResponse.success(PrepaymentDebitDealStatusDto.builder().dealStatus("1").statusDesc("该合同号非多品合同").build());
        }else{
            return IResponse.success(basicDebitRecordService.dealRecordForPrepaymentImmediately(prepaymentInfoDto,this.getBatchDate()));
        }
    }
    @PostMapping(value = "/getPrepaymentDebitOrderValidation")
    @ApiOperation(value = "根据合同号查询提前结清扣款指令是否有效")
    public IResponse<ValidOrInvalidEnum> getPrepaymentDebitOrderValidation(@RequestParam("contractNo") String contractNo) {
        BasicDebitRecord debitRecord = basicDebitRecordService.getOne(Wrappers.<BasicDebitRecord>query().lambda()
                .eq(BasicDebitRecord::getContractNo,contractNo)
                .eq(BasicDebitRecord::getFeeType, FeeTypeEnum.advanceSettle)
        );
        if (EmptyUtils.isNotEmpty(debitRecord)){
            if (debitRecord.getGoingAmt().compareTo(BigDecimal.ZERO)>0 || debitRecord.getDebitStatus().equals(DebitStatusEnum.debiting)){
                return IResponse.success(ValidOrInvalidEnum.valid);
            }else {
                return IResponse.success(ValidOrInvalidEnum.invalid);
            }
        }else{
            return IResponse.success(ValidOrInvalidEnum.invalid);
        }
    }



    @PostMapping(value = "/queryDebitBatchList")
    @ApiOperation(value = "多条件分页获取扣款批次数据")
    public IResponse<IPage<BasicDebitBatch>> queryDebitBatchList(@ModelAttribute DebitBatchCondition debitBatchCondition) {
        Page page = new Page(debitBatchCondition.getPageNumber(), debitBatchCondition.getPageSize());

        /**  批次编号自动去空格 by ZC.GUO  **/
        if(EmptyUtils.isNotEmpty(debitBatchCondition.getBatchNo())){
            debitBatchCondition.setBatchNo(debitBatchCondition.getBatchNo().trim());
        }

        /**  开始时间结束时间自动处理 by ZC.GUO  **/
        if(EmptyUtils.isNotEmpty(debitBatchCondition.getStartDate())){
            debitBatchCondition.setStartDate(DateUtil.beginOfDay(debitBatchCondition.getStartDate()));
        }
        if(EmptyUtils.isNotEmpty(debitBatchCondition.getEndDate())){
            debitBatchCondition.setEndDate(DateUtil.endOfDay(debitBatchCondition.getEndDate()));
        }

        IPage<BasicDebitBatch> debitBatchIPage = basicDebitBatchService.page(page,Wrappers.<BasicDebitBatch>query().lambda()
                .eq(EmptyUtils.isNotEmpty(debitBatchCondition.getBatchStatus()),BasicDebitBatch::getBatchStatus,debitBatchCondition.getBatchStatus())
                .eq(EmptyUtils.isNotEmpty(debitBatchCondition.getDeductBank()),BasicDebitBatch::getDeductBank,debitBatchCondition.getDeductBank())
                .eq(EmptyUtils.isNotEmpty(debitBatchCondition.getBatchNo()),BasicDebitBatch::getBatchNo,debitBatchCondition.getBatchNo())
                .gt(EmptyUtils.isNotEmpty(debitBatchCondition.getStartDate()),BasicDebitBatch::getCreateTime,debitBatchCondition.getStartDate())
                .lt(EmptyUtils.isNotEmpty(debitBatchCondition.getEndDate()),BasicDebitBatch::getCreateTime,debitBatchCondition.getEndDate())
                .orderByDesc(BasicDebitBatch::getCreateTime)
        );
        return IResponse.success(debitBatchIPage);
    }


    @PostMapping(value = "/deleteDebitBatch")
    @ApiOperation(value = "删除扣款批次")
    public IResponse<String> deleteDebitBatch(@ModelAttribute DebitBatchCondition debitBatchCondition) {
        if (ObjectUtils.isNotEmpty(debitBatchCondition.getId())){
            BasicDebitBatch debitBatch = basicDebitBatchService.getById(debitBatchCondition.getId());
            if (ObjectUtils.isNotEmpty(debitBatch)){
                /**  批次操作之前进行锁定 by ZC.GUO  **/
                debitBatch.setIsOperating(YesOrNoEnum.yes);
                if (basicDebitBatchService.lockOrUnlockBatch(debitBatch)){
                    try{
                        String msg = basicDebitBatchService.deleteDebitBatch(debitBatch);
                        /**  处理提前还款扣款指令 by ZC.GUO  **/
                        basicDebitBatchService.scanAndDealPrepaymentDebitOrder();
                        return IResponse.success(msg);
                    }catch (Exception e){
                        log.error("批次{}删除失败！",debitBatch.getBatchNo());
                        throw new AfsBaseException("批次删除失败，请检查批次状态");
                    }finally{
                        /**  无论如何都要解锁 by ZC.GUO  **/
                        debitBatch.setIsOperating(YesOrNoEnum.no);
                        basicDebitBatchService.lockOrUnlockBatch(debitBatch);
                    }
                }else{
                    return IResponse.fail("该批次不可删除，请检查批次状态");
                }
            }else {
                return IResponse.fail("找不到该批次");
            }
        }else{
            return IResponse.fail("找不到该批次");
        }
    }


    @PostMapping(value = "/sendDebitBatch")
    @ApiOperation(value = "发送扣款批次")
    public IResponse<String> sendDebitBatch(@ModelAttribute DebitBatchCondition debitBatchCondition) {
        if (ObjectUtils.isNotEmpty(debitBatchCondition.getId())){
            BasicDebitBatch debitBatch = basicDebitBatchService.getById(debitBatchCondition.getId());
            /**  自动扣款 by ZC.GUO  **/
            /**  批次操作之前进行锁定 by ZC.GUO  **/
            debitBatch.setIsOperating(YesOrNoEnum.yes);
            if (basicDebitBatchService.lockOrUnlockBatch(debitBatch)){
                try{
                    return IResponse.success(basicDebitBatchService.sendDebitBatch(debitBatch, DebitModeEnum.auto));
                }catch (Exception e){
                    log.error("批次{}发送失败！",debitBatch.getBatchNo());
                    return IResponse.fail("发送失败");
                }finally{
                    /**  无论如何都要解锁 by ZC.GUO  **/
                    debitBatch.setIsOperating(YesOrNoEnum.no);
                    basicDebitBatchService.lockOrUnlockBatch(debitBatch);
                }
            }else {
                return IResponse.fail("发送失败");
            }
        }else{
            return IResponse.fail("请选择要发送的批次");
        }
    }
    @PostMapping(value = "/queryDebitBatchResult")
    @ApiOperation(value = "查询扣款结果")
    public IResponse<String> queryDebitBatchResult(@ModelAttribute DebitBatchCondition debitBatchCondition) {
        if (ObjectUtils.isNotEmpty(debitBatchCondition.getId())){
            BasicDebitBatch debitBatch = basicDebitBatchService.getById(debitBatchCondition.getId());
            if (ObjectUtils.isNotEmpty(debitBatch)){
                /**  批次操作之前进行锁定 by ZC.GUO  **/
                debitBatch.setIsOperating(YesOrNoEnum.yes);
                if (basicDebitBatchService.lockOrUnlockBatch(debitBatch)){
                    try{
                        basicDebitBatchService.queryDebitBatchResult(debitBatch,getBatchDate());
                        /**  处理提前还款扣款指令 by ZC.GUO  **/
                        basicDebitBatchService.scanAndDealPrepaymentDebitOrder();
                        return IResponse.success("回盘成功");
                    }catch (Exception e){
                        log.error("批次{}删除失败！",debitBatch.getBatchNo());
                        throw new AfsBaseException("回盘失败，请检查批次状态");
                    }finally{
                        /**  无论如何都要解锁 by ZC.GUO  **/
                        debitBatch.setIsOperating(YesOrNoEnum.no);
                        basicDebitBatchService.lockOrUnlockBatch(debitBatch);
                    }
                }else{
                    return IResponse.fail("回盘失败，请检查批次状态");
                }
            }else {
                return IResponse.fail("找不到该批次");
            }
        }else{
            return IResponse.fail("请选择要查询的批次");
        }
    }


    @PostMapping(value = "/queryDebitBatch")
    @ApiOperation(value = "根据id查询批次信息")
    public IResponse<BasicDebitBatch> queryDebitBatch(@ModelAttribute DebitBatchCondition debitBatchCondition) {
        if (ObjectUtils.isNotEmpty(debitBatchCondition.getId())){
            BasicDebitBatch debitBatch = basicDebitBatchService.getById(debitBatchCondition.getId());
            if (ObjectUtils.isNotEmpty(debitBatch)){
                return IResponse.success(debitBatch);
            }else{
                return IResponse.fail("找不到该批次");
            }
        }else{
            return IResponse.fail("找不到该批次");
        }
    }


    @PostMapping(value = "/generateDebitBatch")
    @ApiOperation(value = "生成扣款批次")
    public IResponse<String> generateDebitBatch(@ModelAttribute DebitBatchCondition debitBatchCondition) {
        int batchNum = basicDebitBatchService.generateDebitBatchByCondition(debitBatchCondition,this.getBatchDate());
        return IResponse.success("扣款批次生成成功,共生成" + batchNum + "个批次！");
    }


    @InitBinder
    public void initBinder(WebDataBinder binder) {
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        dateFormat.setLenient(false);
        binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, true));
    }

    @PostMapping(value = "/queryDebitBatchDetailList")
    @ApiOperation(value = "根据批次分页获取批次明细")
    public IResponse<IPage<DebitBatchDetailVo>> queryDebitBatchDetailList(@ModelAttribute DebitBatchCondition debitBatchCondition) {
        Page page = new Page(debitBatchCondition.getPageNumber(), debitBatchCondition.getPageSize());
        IPage<BasicDebitBatchDetails> debitBatchDetailsIPage = basicDebitBatchDetailsService.page(page,Wrappers.<BasicDebitBatchDetails>query().lambda()
                .eq(BasicDebitBatchDetails::getBatchId,debitBatchCondition.getId())
                .like(ObjectUtils.isNotEmpty(debitBatchCondition.getContractNo()),BasicDebitBatchDetails::getContractNo,debitBatchCondition.getContractNo())
                .like(ObjectUtils.isNotEmpty(debitBatchCondition.getDebitAccountName()),BasicDebitBatchDetails::getDebitAccountName,debitBatchCondition.getDebitAccountName())
                .eq(ObjectUtils.isNotEmpty(debitBatchCondition.getContractStatus()),BasicDebitBatchDetails::getContractStatus,debitBatchCondition.getContractStatus())
                .eq(ObjectUtils.isNotEmpty(debitBatchCondition.getDebitStatus()),BasicDebitBatchDetails::getStatus,debitBatchCondition.getDebitStatus())
                .orderByAsc(BasicDebitBatchDetails::getContractNo)
        );
        return IResponse.success(debitBatchDetailsIPage.convert(new Function<BasicDebitBatchDetails, DebitBatchDetailVo>() {

            @Override
            public DebitBatchDetailVo apply(BasicDebitBatchDetails debitBatchDetails) {

                DebitBatchDetailVo debitBatchDetailVo = new DebitBatchDetailVo();
                BeanUtils.copyProperties(debitBatchDetails,debitBatchDetailVo);

                List<BasicDebitRecord> debitRecordList = basicDebitRecordService.list(Wrappers.<BasicDebitRecord>query().lambda()
                        .eq(BasicDebitRecord::getBatchId,debitBatchDetails.getBatchId())
                        .eq(BasicDebitRecord::getContractNo,debitBatchDetails.getContractNo())
                );

                List<DebitDetailRecordVo> recordList = new ArrayList<>();
                if(CollectionUtils.isNotEmpty(debitRecordList)){
                    debitRecordList.forEach(basicDebitRecord -> {
                        DebitDetailRecordVo debitDetailRecordVo = new DebitDetailRecordVo();
                        BeanUtils.copyProperties(basicDebitRecord,debitDetailRecordVo);
                        recordList.add(debitDetailRecordVo);
                    });
                }else{
                    List<BasicDebitHistory> debitHistoryList = basicDebitHistoryService.list(Wrappers.<BasicDebitHistory>query().lambda()
                            .eq(BasicDebitHistory::getBatchId,debitBatchDetails.getBatchId())
                            .eq(BasicDebitHistory::getContractNo,debitBatchDetails.getContractNo())
                    );
                    if(CollectionUtils.isNotEmpty(debitHistoryList)){
                        debitHistoryList.forEach(basicDebitHistory -> {
                            DebitDetailRecordVo debitDetailRecordVo = new DebitDetailRecordVo();
                            BeanUtils.copyProperties(basicDebitHistory,debitDetailRecordVo);
                            debitDetailRecordVo.setGoingAmt(basicDebitHistory.getDebitAmt());
                            recordList.add(debitDetailRecordVo);
                        });
                    }
                }
                debitBatchDetailVo.setRecordList(recordList);
                return debitBatchDetailVo;
            }
        }));
    }
}
